home *** CD-ROM | disk | FTP | other *** search
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1993, David Koblas (koblas@netcom.com) | */
- /* | | */
- /* | Permission to use, copy, modify, and to distribute this software | */
- /* | and its documentation for any purpose is hereby granted without | */
- /* | fee, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. There is no | */
- /* | representations about the suitability of this software for | */
- /* | any purpose. this software is provided "as is" without express | */
- /* | or implied warranty. | */
- /* | | */
- /* +-------------------------------------------------------------------+ */
-
- #include <X11/Intrinsic.h>
- #include <X11/Shell.h>
- #include <X11/Xaw/Command.h>
- #include <X11/Xaw/Toggle.h>
- #include <X11/Xaw/Form.h>
- #include <X11/Xaw/Label.h>
- #include <X11/Xaw/List.h>
- #include <X11/Xaw/AsciiText.h>
- #include <X11/Xaw/Text.h>
- #include <X11/Xaw/Viewport.h>
- #include <X11/Xaw/Scrollbar.h>
- #include <X11/StringDefs.h>
- #include <stdio.h>
- #include <ctype.h>
-
- #include "misc.h"
-
- #define TAB_DISTANCE 4
-
- static String helpText[] = {
- #include "Help.txt.h"
- };
-
- typedef struct HelpInfo_s {
- char *name, *topic;
- int index;
- int start, stop;
- struct HelpInfo_s *next;
- } HelpInfo;
-
- typedef struct {
- Widget shell;
- int curTopic;
- Widget topicList, topicPort;
- Widget textText, textTitle;
- Widget nextButton, prevButton;
- Widget scrollbar;
- int ninfo;
- String *topics;
- HelpInfo *info;
- } LocalInfo;
-
- static Widget toplevel;
-
- /*
- ** Build heirarchitcal help information structures.
- */
- char *matchGet(char *line, char *pat)
- {
- static char buf[256];
- int len = strlen(pat);
- char *sp, *ep;
-
- if (strncmp(line, pat, len) != 0)
- return NULL;
-
- for (sp = line + len; isspace(*sp); sp++);
- for (ep = sp; isalnum(*ep); ep++);
- strncpy(buf, sp, ep - sp);
- buf[ep-sp] = '\0';
-
- return buf;
- }
-
- static HelpInfo *buildInfo(int *count)
- {
- Boolean nc, flg;
- int depth = 0, stop = -1;
- int i, j;
- char parts[10][20];
- HelpInfo *head = NULL, **nxt = &head, *cur = NULL;
- char *cp, *tp = NULL;
- int idx = 0;
-
- if (count != NULL)
- *count = 0;
-
- for (i = 0; i < XtNumber(helpText); i++) {
- flg = nc = False;
- if ((cp = matchGet(helpText[i], "#BEGIN")) != NULL) {
- int argc;
- char *argv[128];
- char buf[256];
-
- nc = True;
- strcpy(buf, helpText[i]); /* Need R&W buffer */
- StrToArgv(buf, &argc, argv);
- strcpy(parts[depth], argv[1]);
- tp = (argc > 2) ? argv[2] : argv[1];
- } else if ((cp = matchGet(helpText[i], "#PUSH")) != NULL) {
- depth++;
- flg = True;
- } else if ((cp = matchGet(helpText[i], "#POP")) != NULL) {
- if (depth > 0)
- depth--;
- flg = True;
- } else if ((cp = matchGet(helpText[i], "#NL")) != NULL) {
- stop = i;
- } else {
- stop = i;
- }
-
- if (nc) {
- int len;
-
- if (cur != NULL) {
- cur->stop = stop + 1;
- *nxt = cur;
- nxt = &cur->next;
- }
-
-
- cur = XtNew(HelpInfo);
- cur->index = idx++;
- cur->start = i + 1;
- cur->next = NULL;
-
- if (count != NULL)
- (*count)++;
-
- len = 0;
- for (j = 0; j <= depth; j++)
- len += strlen(parts[j]) + 1;
- cur->name = (char*)XtMalloc(len + 1);
- cur->name[0] = '\0';
- for (j = 0; j <= depth; j++) {
- strcat(cur->name, parts[j]);
- strcat(cur->name, ".");
- }
- cur->name[strlen(cur->name)-1] = '\0';
- cur->topic = (char*)XtMalloc(strlen(tp) + 7 + 2 * depth);
- for (j = 0; j < depth * 2; j++)
- cur->topic[j] = ' ';
- cur->topic[j] = '\0';
- strcat(cur->topic, tp);
- strcat(cur->topic, " ");
- } else if (flg) {
- if (cur->start == i)
- cur->start++;
- }
- }
-
- if (cur != NULL) {
- cur->stop = i;
- *nxt = cur;
- nxt = &cur->next;
- }
-
- return head;
- }
-
-
- static void doneCB(Widget w, XtPointer lArg, XtPointer junk)
- {
- LocalInfo *l = (LocalInfo*)lArg;
-
- XtPopdown(l->shell);
- }
-
- static char *buildText(HelpInfo *cur)
- {
- int i, len;
- char *txt;
- char *tp, *cp;
-
- len = 0;
- for (i = cur->start; i < cur->stop; i++)
- len += strlen(helpText[i]) + 2;
-
- tp = txt = (char*)XtCalloc(len + 8, sizeof(char));
- for (i = cur->start; i < cur->stop; i++) {
- /*
- ** Line of all whitespace is a paragraph break.
- */
- for (cp = helpText[i]; *cp != '\0'; cp++)
- if (!isspace(*cp))
- break;
- if (*cp == '\0') {
- *tp++ = '\n';
- *tp++ = '\n';
- continue;
- }
- if (strncmp(helpText[i], "#NL", 3) == 0) {
- *tp++ = '\n';
- continue;
- }
- for (cp = helpText[i]; *cp != '\0'; *tp++ = *cp++);
- *tp++ = ' ';
- }
- *tp++ = '\n';
- *tp = '\0';
-
- return txt;
- }
-
- static void display(LocalInfo *l, HelpInfo *cur)
- {
- char *txt;
- float self, top, shown;
-
- if (cur == NULL)
- cur = l->info;
-
- l->curTopic = cur->index;
-
- txt = buildText(cur);
-
- XtVaSetValues(l->textText, XtNstring, txt, NULL);
- XtVaSetValues(l->textTitle, XtNlabel, cur->topic, NULL);
-
- XtFree((XtPointer)txt);
-
- XtVaSetValues(l->nextButton, XtNsensitive, (cur->next != NULL), NULL);
- XtVaSetValues(l->prevButton, XtNsensitive, (cur->index != 0), NULL);
-
- XtCallActionProc(l->textText, "beginning-of-file", NULL, NULL, 0);
-
- /*
- ** Now position the scrollbar to be visible
- */
-
- XtVaGetValues(l->scrollbar, XtNtopOfThumb, &top,
- XtNshown, &shown,
- NULL);
- self = (float)cur->index / (float)l->ninfo;
- if (self < top || self > top + shown) {
- static String args[] = { "Forward" };
- top = self - shown / 2.0;
- if (top < 0.0)
- top = 0.0;
- if (top + shown > 1.0)
- top = 1.0 - shown;
-
- /*
- ** Scrollbar doesn't notify on a SetThumb()
- ** So we must do it
- */
- XawScrollbarSetThumb(l->scrollbar, top, -1.0);
- XtCallCallbacks(l->scrollbar, XtNjumpProc, (XtPointer)&top);
- }
- }
-
- static void topicCB(Widget w, LocalInfo *l, XawListReturnStruct *list)
- {
- HelpInfo *cur = l->info;
- int i;
-
- for (i = 0; i < list->list_index; i++)
- cur = cur->next;
-
- display(l, cur);
- }
- static void downCB(Widget w, LocalInfo *l, XtPointer junk)
- {
- XtCallActionProc(l->textText, "next-page", NULL, NULL, 0);
- }
- static void upCB(Widget w, LocalInfo *l, XtPointer junk)
- {
- XtCallActionProc(l->textText, "previous-page", NULL, NULL, 0);
- }
- static void prevCB(Widget w, LocalInfo *l, XtPointer junk)
- {
- XawListReturnStruct lrs;
-
- if (l->curTopic == 0)
- return;
-
- lrs.list_index = l->curTopic - 1;
- XawListHighlight(l->topicList, lrs.list_index);
- topicCB(w, l, &lrs);
- }
- static void nextCB(Widget w, LocalInfo *l, XtPointer junk)
- {
- XawListReturnStruct lrs;
-
- if (l->curTopic == l->ninfo - 1)
- return;
-
- lrs.list_index = l->curTopic + 1;
- XawListHighlight(l->topicList, lrs.list_index);
- topicCB(w, l, &lrs);
- }
-
- static LocalInfo *buildPopup(LocalInfo *l, Widget parent)
- {
- Widget shell, form;
- Widget title;
- Widget topicList, topicPort;
- Widget textTitle, textList;
- Widget done, prev, next;
- Widget pgDown, pgUp;
-
- if (l == NULL) {
- HelpInfo *cur;
- int i;
-
- l = XtNew(LocalInfo);
- l->info = buildInfo(&l->ninfo);
-
- l->topics = (String *)XtCalloc(l->ninfo + 1, sizeof(String));
- for (i = 0, cur = l->info; cur != NULL; cur = cur->next, i++)
- l->topics[i] = cur->topic;
- l->topics[i] = NULL;
- l->shell = None;
- }
-
- if (l->shell != None)
- return l;
-
- shell = XtVaCreatePopupShell("helpDialog",
- topLevelShellWidgetClass, GetShell(parent),
- NULL);
-
- form = XtVaCreateManagedWidget("form",
- formWidgetClass, shell,
- XtNborderWidth, 0,
- NULL);
-
- title = XtVaCreateManagedWidget("title",
- labelWidgetClass, form,
- XtNborderWidth, 0,
- XtNtop, XtChainTop,
- XtNbottom, XtChainTop,
- XtNleft, XtChainLeft,
- XtNright, XtChainLeft,
- NULL);
-
- /*
- **
- */
- topicPort = XtVaCreateManagedWidget("topicPort",
- viewportWidgetClass, form,
- XtNtop, XtChainTop,
- XtNbottom, XtChainBottom,
- XtNleft, XtChainLeft,
- XtNright, XtChainLeft,
- XtNfromVert, title,
- XtNallowVert, True,
- XtNforceBars, True,
- NULL);
- topicList = XtVaCreateManagedWidget("topic",
- listWidgetClass, topicPort,
- XtNverticalList, True,
- XtNforceColumns, True,
- XtNdefaultColumns, 1,
- NULL);
-
- /*
- **
- */
- textTitle = XtVaCreateManagedWidget("textTitle",
- labelWidgetClass, form,
- XtNborderWidth, 0,
- XtNfromHoriz, topicPort,
- XtNfromVert, title,
- XtNleft, XtChainLeft,
- XtNright, XtChainRight,
- XtNtop, XtChainTop,
- XtNbottom, XtChainTop,
- XtNresize, False,
- NULL);
-
- textList = XtVaCreateManagedWidget("textText",
- asciiTextWidgetClass, form,
- XtNwrap, XawtextWrapWord,
- XtNtop, XtChainTop,
- XtNbottom, XtChainBottom,
- XtNleft, XtChainLeft,
- XtNright, XtChainRight,
- XtNfromVert, textTitle,
- XtNfromHoriz, topicPort,
- XtNscrollVertical, XawtextScrollAlways,
- XtNdisplayCaret, False,
- NULL);
- {
- Widget sink;
- int tabs[10];
- int i;
-
- for (i = 0; i < XtNumber(tabs); i++)
- tabs[i] = i * TAB_DISTANCE;
-
- XtVaGetValues(textList, XtNtextSink, &sink, NULL);
-
- XawTextSinkSetTabs(sink, XtNumber(tabs), tabs);
- }
-
- /*
- **
- */
- done = XtVaCreateManagedWidget("done",
- commandWidgetClass, form,
- XtNfromVert, textList,
- XtNtop, XtChainBottom,
- XtNbottom, XtChainBottom,
- XtNleft, XtChainLeft,
- XtNright, XtChainLeft,
- NULL);
- next = XtVaCreateManagedWidget("next",
- commandWidgetClass, form,
- XtNfromVert, textList,
- XtNfromHoriz, done,
- XtNtop, XtChainBottom,
- XtNbottom, XtChainBottom,
- XtNleft, XtChainLeft,
- XtNright, XtChainLeft,
- NULL);
- prev = XtVaCreateManagedWidget("prev",
- commandWidgetClass, form,
- XtNfromVert, textList,
- XtNfromHoriz, next,
- XtNtop, XtChainBottom,
- XtNbottom, XtChainBottom,
- XtNleft, XtChainLeft,
- XtNright, XtChainLeft,
- NULL);
- pgDown = XtVaCreateManagedWidget("down",
- commandWidgetClass, form,
- XtNfromVert, textList,
- XtNfromHoriz, topicPort,
- XtNtop, XtChainBottom,
- XtNbottom, XtChainBottom,
- XtNleft, XtChainLeft,
- XtNright, XtChainLeft,
- NULL);
- pgUp = XtVaCreateManagedWidget("up",
- commandWidgetClass, form,
- XtNfromVert, textList,
- XtNfromHoriz, pgDown,
- XtNtop, XtChainBottom,
- XtNbottom, XtChainBottom,
- XtNleft, XtChainLeft,
- XtNright, XtChainLeft,
- NULL);
-
- l->shell = shell;
- l->textText = textList;
- l->textTitle = textTitle;
- l->topicPort = topicPort;
- l->topicList = topicList;
- l->nextButton = next;
- l->prevButton = prev;
- l->scrollbar = XtNameToWidget(topicPort, "vertical");
-
- XawListChange(topicList, l->topics, 0, 0, True);
-
- XtAddCallback(topicList, XtNcallback, (XtCallbackProc)topicCB, (XtPointer)l);
- XtAddCallback(pgDown, XtNcallback, (XtCallbackProc)downCB, (XtPointer)l);
- XtAddCallback(pgUp, XtNcallback, (XtCallbackProc)upCB, (XtPointer)l);
- XtAddCallback(next, XtNcallback, (XtCallbackProc)nextCB, (XtPointer)l);
- XtAddCallback(prev, XtNcallback, (XtCallbackProc)prevCB, (XtPointer)l);
-
- XtAddCallback(done, XtNcallback, doneCB, (XtPointer)l);
- AddDestroyCallback(shell, (void (*)(Widget, void *, XEvent *))doneCB, (XtPointer)l);
-
- return l;
- }
-
- void HelpDialog(Widget parent, String name)
- {
- static LocalInfo *l = NULL;
- int i;
- HelpInfo *cur;
-
- l = buildPopup(l, toplevel);
-
- for (i = 0, cur = l->info; cur != NULL; cur = cur->next, i++)
- if (strcmp(name, cur->name) == 0)
- break;
-
- if (!XtIsRealized(l->shell))
- display(l, cur);
-
- XawListHighlight(l->topicList, cur == NULL ? 0 : i);
-
- XtPopup(l->shell, XtGrabNone);
-
- display(l, cur);
- XMapRaised(XtDisplay(l->shell), XtWindow(l->shell));
- }
-
- void HelpTextOutput(FILE *fd, String name)
- {
- char *txt;
- int col, wlen, i;
- char *tp, *cp, *wstart;
- HelpInfo *head, *cur;
-
- head = buildInfo(NULL);
-
- for (i = 0, cur = head; cur != NULL; cur = cur->next, i++)
- if (strcmp(name, cur->name) == 0)
- break;
-
- if (cur == NULL)
- return;
-
- txt = buildText(cur);
-
- col = wlen = 0;
- for (tp = txt; *tp != '\0'; tp++) {
- if (isspace(*tp) || *tp == '\n') {
- for (i = 0; i < wlen; i++, wstart++)
- putc(*wstart, fd);
- col += wlen;
- wlen = 0;
- if (*tp == '\t') {
- do {
- putc(' ', fd);
- col++;
- } while (col % TAB_DISTANCE != 0);
- } else if (*tp == '\n') {
- putc(*tp, fd);
- col = 0;
- } else {
- putc(*tp, fd);
- col++;
- }
-
- if (col > 75) {
- putc('\n', fd);
- col = 0;
- }
- } else if (wlen != 0) {
- if (col != 0 && (wlen + col > 75)) {
- putc('\n', fd);
- col = 0;
- }
- wlen++;
- } else {
- wlen = 1;
- wstart = tp;
- }
- }
- for (i = 0; i < wlen; i++, wstart++)
- putc(*wstart, fd);
- if (col != 0)
- putc('\n', fd);
-
- XtFree((XtPointer)txt);
- }
-
- static void helpAction(Widget w, XEvent *event, String *prms, Cardinal *nprms)
- {
- if (*nprms != 1) {
- fprintf(stderr,"Help called with wrong number of params\n");
- return;
- }
-
- HelpDialog(w, prms[0]);
- }
-
- void HelpInit(Widget top)
- {
- static XtActionsRec act = { "PaintHelp", (XtActionProc)helpAction };
-
- XtAppAddActions(XtWidgetToApplicationContext(top), &act, 1);
-
- toplevel = top;
- }
-